package com.asm.blog.config;


import com.asm.blog.shiro.AccountRealm;
import com.asm.blog.shiro.JwtFilter;
import org.apache.shiro.mgt.SessionsSecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 根据 shiro-redis文档整合  https://github.com/alexxiyang/shiro-redis/blob/master/docs/README.md#spring-boot-starter
 *
 *
 */
@Configuration  // 启动 即加载
public class ShiroConfig {

  /*  @Autowired  打开会报错
    RedisSessionDAO redisSessionDAO;*/

/*    @Autowired  打开会报错
    RedisCacheManager redisCacheManager;*/

    /**
     * 实例一个 jwtFilter交给 Bean管理，方便下面方法使用
     */

    @Autowired
    JwtFilter jwtFilter;


    // 设置 Web会话管理器 交给 bean管理
    @Bean
    public SessionManager sessionManager(RedisSessionDAO redisSessionDAO) {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();

        // inject redisSessionDAO
        sessionManager.setSessionDAO(redisSessionDAO);

        // other stuff...

        return sessionManager;
    }
    // shiro安全管理器 设置 [自定义的realm]  , 最后交给 bean管理    【一般 复制粘贴就行 稍微配置就行】
    @Bean
    public SessionsSecurityManager securityManager(AccountRealm accountRealm,
                                                   SessionManager sessionManager,
                                                   RedisCacheManager redisCacheManager) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(accountRealm);

        //inject sessionManager
        securityManager.setSessionManager(sessionManager);

        // inject redisCacheManager
        securityManager.setCacheManager(redisCacheManager);

        // other stuff...

        return securityManager;
    }

    /**
     * Shiro过滤器链定义   添加 jwt路径定义    【一般 复制粘贴就行 稍微配置就行】
     *
     * ---------------------------------------------------------------------
     *                                                                     /
     *     1. 这个版本的shiro必须要这个bean 很奇怪 不能注释掉                   /
     *     2. 过滤器要先 addPathDefinitions()                               /
     *     3. 然后 getFilterChainMap() 出来                                 /
     *     4. 再 ShiroFilterFactoryBean.setFilterChainDefinitionMap()      /
     *                                                                     /
     * ====================================================================
     * @return
     */
    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
        Map<String, String> filterMap = new LinkedHashMap<>();
        /**
         * 这里设置 所有链接 访问 都会进入这个 jwt过滤
         * -----------------------------------------------------------
         *                                                           /
         *   注意：这里不建议 用authc anon等其他连接，会出现 第一次访问失败 /
         *                                                           /
         * ===========================================================
         */
        filterMap.put("/**", "jwt"); // 没配置 jwt之前可以改authc  先测试
        filterMap.put("/test/anon","anon");
        filterMap.put("/logout","anon");
        filterMap.put("/test/user","user");
        filterMap.put("/test/auth","authc");
//        filterMap.put("/test/admin","roles[admin]");
        chainDefinition.addPathDefinitions(filterMap);
        return chainDefinition;
    }

    /**
     * Shiro过滤器 设置 [自定义的 JwtFilter过滤器]   【一般 复制粘贴就行 稍微配置就行】
     *
     * @param securityManager
     * @param shiroFilterChainDefinition
     * @return
     *
     * 注意 SecurityManager 默认使用的是java.lang；需要自己手写导入一下 import org.apache.shiro.mgt.SecurityManager
     * 注意 Filter          导入的是 javax.servlet.Filter
     */
    @Bean("shiroFilterFactoryBean")
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager,
                                                         ShiroFilterChainDefinition shiroFilterChainDefinition) {
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        factoryBean.setSecurityManager(securityManager);
        // 设置 自定义 jwt过滤器
        Map<String, Filter> filters = new HashMap<>();
        filters.put("jwt", jwtFilter);
        factoryBean.setFilters(filters);


        // 获取上面 方法的 获取过滤器链映射
        Map<String, String> filterMap = shiroFilterChainDefinition.getFilterChainMap();
        System.out.println("=========================" + filterMap.toString());

        factoryBean.setLoginUrl("/test/tipLogin"); // 设置登录页面 【是静态页面】【引导未登录(和退出)跳转此页面】
        factoryBean.setFilterChainDefinitionMap(filterMap);
        return factoryBean;
    }



}
